#include "XRenderSystem.h"
#include "xLogManager.h"
#include "xShader.h"
#include "xPass.h"

namespace XE
{


	XRenderSystem::XRenderSystem(HINSTANCE instatce)
		:m_Instace(instatce),m_PrimaryRenderTarget(NULL),m_pDepthRenderSurface(NULL),
		m_pBoneMatrix(NULL),m_BoneCount(9), m_RenderFps(true),m_Fps(100.0f)
	{
		ZeroMemory(m_pColorRenderSurface,sizeof(m_pColorRenderSurface));

		ZeroMemory(m_TextureSate,sizeof(xTexture*)*8);
		
		
	
	}

	XRenderSystem::~XRenderSystem()
	{
		SafeDelete(m_PrimaryRenderTarget)
		DestoryAllAttachRenderTarget();

	}

	HRESULT XRenderSystem::InitRenderSystem( const RenderConfig& Rconfig)
	{

		m_RenderConfig = Rconfig;
		return X_OK;
	}


	HRESULT  XRenderSystem::RenderOneFrame(DWORD elapse)
	{




		size_t AttachSize = m_AttachRenderTarget.size();
		for(size_t i  =0;i<AttachSize;++i)
		{
			m_AttachRenderTarget.at(i)->update(this);
		}

		if(m_PrimaryRenderTarget!=NULL)
		{
			m_PrimaryRenderTarget->update(this);

		}
		//*
		static DWORD lasttime = 0;
		static float nframes = 0;
		lasttime+=elapse;
		++nframes;
		if(lasttime>1000)
		{
			m_Fps = 1000.0f/(lasttime/nframes);
			lasttime=0;
			nframes = 0.0f;
            
		}
//*/
	//	elapse = max(1,elapse);
		//m_Fps =1000/elapse;



		if( isRenderFps())
		{
			Renderfps();
		}




		return X_OK;
	}



	HRESULT  XRenderSystem::SetBoneMatrixArray(const xMatrix* pMatrix,WORD BoneCount)
	{
		m_pBoneMatrix = pMatrix;
		m_BoneCount = BoneCount;
		return X_OK;

	}


	const  xMatrix* XRenderSystem::GetBoneMatrixArray(WORD& count)
	{
          count = m_BoneCount;
		  return m_pBoneMatrix;
	}

	xRenderTarget* XRenderSystem::\
		CreateAttachRenderTarget(const xString& name, const RenderConfig& renderconfig)
	{
		xRenderTarget* pTarget = GetAttachRenderTarget(name);
		if(pTarget!=NULL)
		{
			xLogMessager::getSingleton().logMessage("create Rendetarget Fail ,has same name RenderTarget");
			return NULL ;
		}


		pTarget = CreateAttachRenderTargetImplement(name,renderconfig);
		if(pTarget==NULL)
		{
			xLogMessager::getSingleton().logMessage\
				("create Attach RenderTarget Fial, CreateAttachRenderTargetImplement Fail");
		    return NULL;
		}

		m_AttachRenderTarget.push_back(pTarget);

		return pTarget;
	}

	bool XRenderSystem::DestoryAttachRenderTarget(xRenderTarget* pTarget)
	{
		xRenderTargetVector::iterator it = m_AttachRenderTarget.begin();
		xRenderTargetVector::iterator endit = m_AttachRenderTarget.end();
		for(;it!=endit;++it)
		{
			if((*it)==pTarget)
			{
				delete *it;
				m_AttachRenderTarget.erase(it);
				return true;
			}
		}
		return false;	
	}


	bool XRenderSystem::DestoryAttachRenderTarget(const xString& name)
	{

		xRenderTargetVector::iterator it = m_AttachRenderTarget.begin();
		xRenderTargetVector::iterator endit = m_AttachRenderTarget.end();
		for(;it!=endit;++it)
		{
			if((*it)->GetName()==name)
			{
				delete *it;
				m_AttachRenderTarget.erase(it);
				return true;
			}
		}
		return false;	


	}

	xRenderTarget* XRenderSystem::GetAttachRenderTarget(const xString& name)
	{

		xRenderTargetVector::iterator it = m_AttachRenderTarget.begin();
		xRenderTargetVector::iterator endit = m_AttachRenderTarget.end();
		for(;it!=endit;++it)
		{
			if((*it)->GetName()==name)
			{
				return *it;
			}
		}
		return NULL;

	}



	void  XRenderSystem::DestoryAllAttachRenderTarget()
	{
		xRenderTargetVector::iterator it = m_AttachRenderTarget.begin();
		xRenderTargetVector::iterator endit = m_AttachRenderTarget.end();
		for(;it!=endit;++it)
		{
			delete *it;
		}
		m_AttachRenderTarget.clear();
		return ;

	}


	HRESULT	 XRenderSystem::BeginShader(const xShaderPtr& pShader)
	{
		m_pShader = pShader;
		if(m_pShader.isNull())
			return X_FAIL;

		
	/*	if(FAILED(m_pShader->(m_pShader->GetActiveTechniqueName())))
		{
			xLogMessager::getSingleton().logMessage("SetAcitve Technique Fail,shader name is"+pShader->GetName());
			m_pShader.setNull();
			return  X_FAIL;
		}*/


		UINT passNum = 0;
		if(FAILED(m_pShader->Begin(/*passNum,*/D3DXFX_DONOTSAVESTATE|D3DXFX_DONOTSAVESHADERSTATE)))
		{
			xLogMessager::getSingleton().logMessage("SetAcitve Technique Fail,shader name is"+pShader->GetName());
			m_pShader.setNull();
			return  X_FAIL;
		}



		return	X_OK;


	}

	HRESULT   XRenderSystem::EndShader()
	{
		if(m_pShader.isNull())
			return X_FAIL;
		return m_pShader->End();

	}


	HRESULT XRenderSystem::BeginPass( UINT passindex, xPass* pass) 
	{
		m_pPass = pass;
		if(m_pPass==NULL)
			return X_FAIL;
		
		m_pPass->Begin(this);
		m_pShader->BeginPass( passindex);
		return	X_OK;

	}

	HRESULT XRenderSystem::EndPass()
	{
		//if(m_pPass==NULL)
		//	return X_FAIL;

		if(FAILED( m_pShader->EndPass()))
			return X_FAIL;
		return m_pPass->End(this);


	}


	 xSurfacePtr XRenderSystem::GetRenderColorSuface(UINT index)
	{
		if(index>3)
			return xSurfacePtr();
		return xSurfacePtr(m_pColorRenderSurface[index]);
	}

	const  xTexture* XRenderSystem::GetTexture(UINT index) const 
	{
		if(index>7)
			return NULL;
		return m_TextureSate[index];
	}


	HRESULT XRenderSystem::SetTexture(UINT index,const xTexture* pTexture)
	{
		if(index>7)
			return X_FAIL;
		m_TextureSate[index] =pTexture;
		return X_OK;
	}




}